//
// PrintCommand.cs
//
// Author: 
//  Fredy Ramirez <framirez@pacificcoolwave.com>
//
// Copyright (C) 2011 Fredy Ramirez (http://www.pacificcoolwave.com)
//
//  Creation date: Aug 24, 2011
//  Last modification: 

/*
The MIT License

Copyright (C) 2011 Fredy Ramirez (http://www.pacificcoolwave.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 */

using System;
using Gtk;
using Cairo;
using Pcw.PcwTextEditor.ExtensionModel;
using Pcw.PcwTextEditor.PcwDocument;

namespace Pcw.PcwTextEditor.Commands
{
	/// <summary>
	/// Send document to print.
	/// </summary>
	class PrintCommand : ICommand
	{
		private string print_text = "";
		
		private string id = "";		
		private MenuItem menu_item;
		private ToolItem tool_item;

		private static double header_height = 10; // mm
		private static double header_gap = 3;	  // mm
		
		private PrintOperation print;

		private double font_size = 10.0;
		private int lines_per_page;
		private string[] lines;
		private int num_lines;
		private int num_pages;		
		
		public string Id
		{
			set {id = value;}
			get{return id;}
		}
		
		public MenuItem MenuObject 
		{
			set 
			{
				menu_item = value;
				menu_item.Sensitive = false;
			}
		}
		
		public ToolItem ToolObject 
		{
			set 
			{
				tool_item = value;
				tool_item.Sensitive = false;
			}
		}		
		
		public void Run ()
		{			
			print = new PrintOperation ();
	
			// Set the Print Operation methods
			
			print.BeginPrint += new BeginPrintHandler (OnBeginPrint);
			print.DrawPage += new DrawPageHandler (OnDrawPage);
			print.EndPrint += new EndPrintHandler (OnEndPrint);		
			
			// Run the Print Operation and tell it what it should do (Export, Preview, Print, PrintDialog)
			// And provide a parent window if applicable
			print.Run (PrintOperationAction.PrintDialog, TextEditor.MainWin);
						
		}
		
		public void DocumentChanged()
		{	
		}

		public void OnLoadDocument ()
		{
			SetSensitive(true);			
		}

		public void OnSaveDocument ()
		{
		}

		public void OnCreateDocument ()
		{
		}
		
		public void OnCloseDocument ()
		{
			if (TextEditor.MainWin.Documents.Count == 0)
				SetSensitive(false);
		}
		
		public void OnChangeDocument ()
		{
		}
		
		public void OnSelectDocument ()
		{
		}
		
		private void SetSensitive(bool b) 
		{
			if (menu_item != null)
				menu_item.Sensitive = b;
			if (tool_item != null)
				tool_item.Sensitive = b;			
		}
		
		private void OnBeginPrint (object obj, Gtk.BeginPrintArgs args)
		{
			string contents;
			double height;

			// Get the Context of the Print Operation
			PrintContext context = args.Context;
			
			AddTextInfo("Pango.Scale.PangoScale", Pango.Scale.PangoScale.ToString());
			AddTextInfo("PrintContext Heigh", context.Height.ToString());
			AddTextInfo("PrintContext Width", context.Width.ToString());
			AddTextInfo("PrintContext DpiX", context.DpiX.ToString());
			AddTextInfo("PrintContext DpiY", context.DpiY.ToString());			
                
			// Get the Height of the Context
			height = context.Height;
              
			// From the FontSize and the Height of the Page determine the 
			// Lines available per page
			lines_per_page = (int)Math.Floor(height / font_size);
                
			// Load the file to be printed
			contents = TextEditor.MainWin.CurrDocument.ViewText.Buffer.Text + "\n\n" + print_text;;

			// Split the Content into seperate lines
			lines = contents.Split('\n');                
                
			// Get the Number of lines
			num_lines = lines.Length;
                
			// Calculate the Number of Pages by how many lines there are 
			// and how many lines are available per page
			num_pages = (num_lines - 1) / lines_per_page + 1;
                
			// Tell the Print Operation how many pages there are
			print.NPages = num_pages;
		}
		
		private void OnEndPrint (object obj, Gtk.EndPrintArgs args)
		{
		}
		
		private void OnDrawPage (object obj, Gtk.DrawPageArgs args)
		{
			// Create a Print Context from the Print Operation
			using (PrintContext context = args.Context) 
			{
				
				// Create a Cairo Context from the Print Context				
				using (Cairo.Context cr = context.CairoContext)
				{	                
					// Get the width of the Print Context
					//double width = context.Width;
					double width = context.Width - Mm2Dot(10, context.DpiX);
		
					// Create a rectangle to be used for the Content
					//cr.Rectangle (0, 0, width, header_height);
					//cr.SetSourceRGB (0.8, 0.8, 0.8);
					//cr.FillPreserve ();
					
					header_height = Mm2Dot(header_height, context.DpiY);
					header_gap = Mm2Dot(header_gap, context.DpiY);
					
					cr.Rectangle (0, 0, width, header_height);
					cr.SetSourceRGB (0.8, 0.8, 0.8);
					cr.FillPreserve ();	
		
					// Create a Stroke to outline the Content
					cr.SetSourceRGB (0, 0, 0);
					//cr.LineWidth = 1;
					cr.LineWidth = Mm2Dot(0.5, context.DpiY);
					cr.Stroke();
		
					// Create a Pango Layout for the Text
					Pango.Layout layout = context.CreatePangoLayout ();
		                
					// Set the Font and Font Size desired
					Pango.FontDescription desc = Pango.FontDescription.FromString ("sans 14");
					layout.FontDescription = desc;
		                
					// Create a Header with the FileName and center it on the page
					layout.SetText (TextEditor.MainWin.CurrDocument.DocInfo.NameWithPath);
					layout.Width = (int)width;
					layout.Alignment = Pango.Alignment.Center;
		
					// Get the Text Height from the Height of the layout and the Height of the Page
					int layoutWidth, layoutHeight;
					layout.GetSize (out layoutWidth, out layoutHeight);
					double textHeight = (double)layoutHeight / Pango.Scale.PangoScale;
		
					// Move to the Footer
					cr.MoveTo (width/2, (header_height - textHeight) / 2);
					Pango.CairoHelper.ShowLayout (cr, layout);
		
					// Set the Page Number in the Footer with a right alignment
					string pageStr = String.Format ("{0}/{1}", args.PageNr + 1, num_pages);
					layout.SetText (pageStr);
					layout.Alignment = Pango.Alignment.Right;
		
					//cr.MoveTo (width - 2, (header_height - textHeight) / 2);
					cr.MoveTo (width - Mm2Dot(2, context.DpiY), (header_height - textHeight) / 2);
					Pango.CairoHelper.ShowLayout (cr, layout);
		
					// Create a new Pango Layout for the Content
					layout = null;
					layout = context.CreatePangoLayout ();
		
					// Set the Description of the Content
					//desc = Pango.FontDescription.FromString ("mono");
					//desc.Size = (int)(font_size * Pango.Scale.PangoScale);
					
					//desc = Pango.FontDescription.FromString ("sans 10");
					
					desc.Family = ("sans");
					desc.Size = (int)(font_size * Pango.Scale.PangoScale);

					layout.FontDescription = desc;
		                
					// Move to the beginning of the Content, which is after the Header Height and Gap
					cr.MoveTo (0, header_height + header_gap);
		              
					int line = args.PageNr * lines_per_page;
		            
					layout.GetSize (out layoutWidth, out layoutHeight);
					textHeight = (double)layoutHeight / Pango.Scale.PangoScale;
					
					// Draw the lines on the page according to how many lines there are left and how many lines can fit on the page
					for (int i=0; i < lines_per_page && line < num_lines; i++)
					{
						layout.SetText (lines[line]);
						Pango.CairoHelper.ShowLayout (cr, layout);
						//cr.RelMoveTo (0, font_size);
						cr.RelMoveTo (0, textHeight);
						line++;
					}
		                
					layout = null;
				}
			}
		}
		
		private void AddTextInfo(string label, string info)
		{
			print_text = print_text + label + " " + info + "\n";
		}
		
		private double Mm2Dot(double mm, double dpi)
		{
			return (mm * dpi) / 25.4;
		}
	}
}

















